module nazo.token;
/**
 * スペシャルトークンを使いやすい形に変換します。
 * License: Public Domain
 */
import std.date;

pure int timestamp_hour(){
  return toInt(__TIME__[0..2]);
}

pure int timestamp_minute(){
  return toInt(__TIME__[3..5]);
}

pure int timestamp_second(){
  return toInt(__TIME__[6..8]);
}

pure int timestamp_year(){
  return toInt(__DATE__[7..11]);
}

pure int timestamp_month(){
  return monthToInt(__DATE__[0..3]);
}

pure int timestamp_day(){
  return toInt(__DATE__[4..6]);
}

pure int toInt(string str){
  int rv;
  foreach(c;str){
    rv *= 10;
    rv += toInt(c);
  }
  return rv;
}

static assert(toInt("123")==123);

pure int toInt(char c){
  if(c==' ')
    return 0;
  assert(c>='0'&&c<='9');
  return c-'0';
}
static assert(toInt(' ')==0);
static assert(toInt('3')==3);

pure int monthToInt(string str){
  switch(str){
    case "Jan":return 1;
    case "Feb":return 2;
    case "Mar":return 3;
    case "Apr":return 4;
    case "May":return 5;
    case "Jun":return 6;
    case "Jul":return 7;
    case "Aug":return 8;
    case "Sep":return 9;
    case "Oct":return 10;
    case "Nov":return 11;
    case "Dec":return 12;
    default:
  }
  assert(0, "Invalid String: "~str);
}

pure d_time makeTime(d_time hour, d_time min, d_time sec, d_time ms){
  return hour*TicksPerHour+min*TicksPerMinute+sec*TicksPerSecond+ms*TicksPerMs;
}

pure d_time makeDay(d_time year, d_time month, d_time date){
  return _makeDay(cast(int)(year + floor(month,12)),dmod(month,12),date);
}

pure d_time _makeDay(int y, int m, d_time date){
  return Day(TimeFromYear(y) + cast(d_time)getMdays(m) * msPerDay + (LeapYear(y)&&m>=2?msPerDay:0))+date-1;
}

pure d_time floor(d_time d, int divisor){
  return (d-(d<0?divisor-1:0))/divisor;
}

pure int dmod(d_time n, d_time d){
  return cast(int)(n%d+(n%d<0?d:0));
}

pure int Day(d_time t){
  return cast(int)floor(t,msPerDay);
}

pure int LeapYear(int y){
  return ((y & 3) == 0 && (y % 100 || (y % 400) == 0));
}

pure int DayFromYear(int y){
  return cast(int) (365 * (y - 1970) +
                    floor((y - 1969),4) -
                    floor((y - 1901),100) +
                    floor((y - 1601),400));
}

pure d_time TimeFromYear(int y){
  return cast(d_time)msPerDay*DayFromYear(y);
}

pure int getMdays(int m){
  assert(m<12);
  return [0,31,59,90,120,151,181,212,243,273,304,334][m];
}

d_time makeDate(d_time day, d_time time){
  if(day==d_time_nan||time==d_time_nan)
    return d_time_nan;
  return day*TicksPerDay+time;
}

d_time LocalTZA(){
  return 9*TicksPerHour;///Bugs: -09:00(Japan, Tokyo)固定になってる
}

import std.stdio;

///コンパイル時間を返します。
d_time getCompileTime(){
  return makeDate(makeDay(timestamp_year(),timestamp_month()-1,timestamp_day()),makeTime(timestamp_hour(),timestamp_minute(),timestamp_second(),0) - LocalTZA());
}

///コンパイル時間を返します。
Date getTimeStamp(){
  static Date d = {
    timestamp_year(),
    timestamp_month(),
    timestamp_day(),
    timestamp_hour(),
    timestamp_minute(),
    timestamp_second()
  };
  return d;
}
